package com.nbsaas.nbmall.common.rest.resource;

import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.EntPayService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.EntPayServiceImpl;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.binarywang.wxpay.util.XmlConfig;
import com.haoxuer.bigworld.member.data.entity.TenantUser;
import com.haoxuer.bigworld.pay.data.dao.TenantAccountDao;
import com.haoxuer.bigworld.pay.data.entity.CashConfig;
import com.haoxuer.bigworld.pay.data.enums.FeeType;
import com.haoxuer.bigworld.pay.data.enums.SendState;
import com.haoxuer.bigworld.pay.plugins.service.impl.PayServiceImpl;
import com.haoxuer.discover.trade.api.domain.request.TradeRequest;
import com.haoxuer.discover.trade.data.dao.TradeAccountDao;
import com.haoxuer.discover.trade.data.entity.TradeAccount;
import com.haoxuer.discover.trade.data.enums.ChangeType;
import com.nbsaas.nbmall.common.api.apis.TenantCashApi;
import com.nbsaas.nbmall.common.api.domain.list.TenantCashList;
import com.nbsaas.nbmall.common.api.domain.page.TenantCashPage;
import com.nbsaas.nbmall.common.api.domain.request.*;
import com.nbsaas.nbmall.common.api.domain.response.TenantCashResponse;
import com.nbsaas.nbmall.common.data.dao.SiteTenantDao;
import com.nbsaas.nbmall.common.data.dao.TenantCashDao;
import com.nbsaas.nbmall.common.data.entity.SiteTenant;
import com.nbsaas.nbmall.common.data.entity.TenantCash;
import com.nbsaas.nbmall.common.rest.convert.TenantCashResponseConvert;
import com.nbsaas.nbmall.common.rest.convert.TenantCashSimpleConvert;
import com.haoxuer.bigworld.tenant.data.entity.Tenant;
import com.haoxuer.discover.config.utils.ConverResourceUtils;
import com.haoxuer.discover.data.page.Filter;
import com.haoxuer.discover.data.page.Order;
import com.haoxuer.discover.data.page.Page;
import com.haoxuer.discover.data.page.Pageable;
import com.haoxuer.discover.data.utils.FilterUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import com.haoxuer.bigworld.member.rest.conver.PageableConver;
import com.haoxuer.bigworld.tenant.util.TenantBeanUtils;
import com.haoxuer.bigworld.pay.data.dao.CashConfigDao;
import com.haoxuer.bigworld.member.data.dao.TenantUserDao;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Transactional
@Component
public class TenantCashResource implements TenantCashApi {

    @Autowired
    private TenantCashDao dataDao;

    @Autowired
    private CashConfigDao cashConfigDao;
    @Autowired
    private TenantUserDao creatorDao;

    @Autowired
    private TenantAccountDao basicTradeAccountDao;

    @Autowired
    private TradeAccountDao tradeAccountDao;

    @Autowired
    private SiteTenantDao tenantDao;

    @Override
    public TenantCashResponse back(TenantCashDataRequest request) {
        TenantCashResponse result = new TenantCashResponse();
        TenantCash temp = dataDao.findById(request.getId());

        if (temp == null) {
            result.setCode(501);
            result.setMsg("无效信息");
            return result;
        }
        if (temp.getSendState() == SendState.send) {
            result.setCode(502);
            result.setMsg("该提现单已经支付");
            return result;
        }
        if (temp.getSendState() == SendState.back) {
            result.setCode(502);
            result.setMsg("该提现单已经退回");
            return result;
        }
        TradeAccount account = temp.getTradeAccount();
        if (account == null) {
            result.setCode(505);
            result.setMsg("单据无付款账号");
            return result;
        }

        TradeAccount paymentAccount = basicTradeAccountDao.special(request.getTenant(), "platform_payment");

        TradeRequest cashRequest = new TradeRequest();
        cashRequest.setAmount(temp.getMoney());
        cashRequest.setFrom(paymentAccount.getId());
        cashRequest.setTo(account.getId());
        cashRequest.setChangeType(ChangeType.from(1001, "提现退回"));
        cashRequest.setNote("提现退回");
        tradeAccountDao.trade(cashRequest);


        BigDecimal fee = temp.getFee();
        if (fee==null){
            fee=new BigDecimal(0);
        }
        if (fee.compareTo(new BigDecimal("0.0001"))>0){
            TradeAccount feeAccount = basicTradeAccountDao.special(request.getTenant(), "platform_feeAccount");
            TradeRequest feeCashRequest = new TradeRequest();
            feeCashRequest.setAmount(fee);
            feeCashRequest.setFrom(feeAccount.getId());
            feeCashRequest.setTo(account.getId());
            feeCashRequest.setChangeType(ChangeType.from(1001, "手续费提现退回"));
            feeCashRequest.setNote("手续费提现退回");
            tradeAccountDao.trade(feeCashRequest);
        }
        temp.setSendState(SendState.back);
        return result;
    }

    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
    public TenantCashResponse send(TenantCashDataRequest dataRequest) {
        TenantCashResponse result = new TenantCashResponse();
        TenantCash temp = dataDao.findById(dataRequest.getId());

        if (temp == null) {
            result.setCode(501);
            result.setMsg("无效信息");
            return result;
        }
        CashConfig cashConfig = temp.getCashConfig();
        if (cashConfig == null) {
            result.setCode(502);
            result.setMsg("提现单无配置信息");
            return result;
        }
        if (temp.getSendState() == SendState.send) {
            result.setCode(502);
            result.setMsg("该提现单已经支付");
            return result;
        }
        if (temp.getSendState() == SendState.back) {
            result.setCode(503);
            result.setMsg("该提现单已经退回");
            return result;
        }
        if (temp.getSendState() == SendState.fail) {
            result.setCode(504);
            result.setMsg("该提现单无法处理");
            return result;
        }
        XmlConfig.fastMode = true;
        EntPayRequest request = new EntPayRequest();
        request.setAmount(temp.getMoney().multiply(new BigDecimal(100)).intValue());
        request.setPartnerTradeNo(temp.getNo());
        request.setReUserName(temp.getName());
        request.setCheckName("FORCE_CHECK");
        request.setDescription(temp.getNote());
        request.setOpenid(temp.getOpenId());
        request.setSpbillCreateIp("119.23.149.178");

        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(cashConfig.getAppId());
        payConfig.setMchId(cashConfig.getMchId());
        payConfig.setMchKey(cashConfig.getMchKey());
        payConfig.setKeyPath(cashConfig.getKeyPath());
        //payConfig.setSignType("MD5");
        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        EntPayService entPayService = new EntPayServiceImpl(wxPayService);
        try {
            EntPayResult entPayResult = entPayService.entPay(request);
            temp.setSendState(SendState.send);
            temp.setBussNo(entPayResult.getPaymentNo());
        } catch (WxPayException exception) {
            result.setCode(503);
            result.setMsg("付款失败");
            result.setMsg(exception.getErrCodeDes());
            temp.setDemo(exception.getErrCodeDes());
            exception.printStackTrace();
        }
        return result;
    }

    @Override
    public TenantCashResponse create(TenantCashDataRequest request) {
        TenantCashResponse result = new TenantCashResponse();

        if (request.getMoney() == null || request.getMoney().compareTo(new BigDecimal(0)) <= 0) {
            result.setCode(-1);
            result.setMsg("无效金额");
            return result;
        }
        SiteTenant tenant = tenantDao.findById(request.getTenant());
        if (tenant == null) {
            result.setCode(1001);
            result.setMsg("无效token");
            return result;
        }
        if (request.getOpenId() == null) {
            result.setCode(1002);
            result.setMsg("无效微信用户");
            return result;
        }

        if (tenant.getTradeAccount() == null) {
            tenant.setTradeAccount(tradeAccountDao.initNormal());
        }
        if (tenant.getTradeAccount().getAmount().compareTo(request.getMoney()) < 0) {
            result.setCode(-303);
            result.setMsg("余额不足");
            return result;
        }

        TradeAccount paymentAccount = basicTradeAccountDao.special(request.getTenant(), "platform_payment");

        TradeAccount feeAccount = basicTradeAccountDao.special(request.getTenant(), "platform_feeAccount");


        CashConfig cashConfig = cashConfigDao.one(Filter.eq("tenant.id", request.getTenant()),
                Filter.eq("key", request.getKey()));
        BigDecimal fee = null;
        BigDecimal money = null;
        if (cashConfig == null) {
            result.setCode(503);
            result.setMsg("提现配置没设置");
            return result;
        }
        FeeType feeType = cashConfig.getFeeType();
        if (feeType == null) {
            feeType = FeeType.single;
        }
        if (feeType == FeeType.single) {
            fee = cashConfig.getFee();
        } else {
            BigDecimal rate = cashConfig.getRate();
            if (rate == null) {
                rate = new BigDecimal(0);
            }
            fee = request.getMoney().multiply(rate).divide(new BigDecimal(100));
        }
        if (fee == null) {
            fee = new BigDecimal(0);
        }
        if (fee.compareTo(new BigDecimal(0.001)) > 0) {
            money = request.getMoney().subtract(fee);
            if (money.compareTo(new BigDecimal(0.001)) < 0) {
                result.setCode(-304);
                result.setMsg("手续费大于提现金额");
                return result;
            }

            TradeAccount userAccount = tenant.getTradeAccount();
            TradeRequest feeRequest = new TradeRequest();
            feeRequest.setAmount(fee);
            feeRequest.setFrom(userAccount.getId());
            feeRequest.setTo(feeAccount.getId());
            feeRequest.setChangeType(ChangeType.from(3, "手续费"));
            feeRequest.setNote("手续费");
            tradeAccountDao.trade(feeRequest);
        } else {
            money = request.getMoney();
        }

        TradeAccount userAccount = tenant.getTradeAccount();
        TradeRequest cashRequest = new TradeRequest();
        cashRequest.setAmount(money);
        cashRequest.setFrom(userAccount.getId());
        cashRequest.setTo(paymentAccount.getId());
        cashRequest.setChangeType(ChangeType.from(2, "提现"));
        cashRequest.setNote("微信提现");
        tradeAccountDao.trade(cashRequest);

        TenantCash shopCash = new TenantCash();
        shopCash.setTradeAccount(userAccount);
        shopCash.setCashConfig(cashConfig);
        shopCash.setName(request.getName());
        shopCash.setMoney(money);
        shopCash.setSendState(SendState.init);
        shopCash.setOpenId(request.getOpenId());
        shopCash.setNo(PayServiceImpl.getOrderNo());
        shopCash.setNote("微信余额提现");
        shopCash.setFee(fee);
        shopCash.setCash(request.getMoney());
        shopCash.setTenant(Tenant.fromId(request.getTenant()));
        shopCash.setPhone(request.getPhone());
        shopCash.setIdNo(request.getNo());
        shopCash.setAppId(cashConfig.getAppId());
        shopCash.setTradeAccount(userAccount);
        shopCash.setCreator(TenantUser.fromId(request.getUser()));
        dataDao.save(shopCash);
        result.setId(shopCash.getId());
        return result;
    }

    @Override
    public TenantCashResponse update(TenantCashDataRequest request) {
        TenantCashResponse result = new TenantCashResponse();
        if (request.getId() == null) {
            result.setCode(501);
            result.setMsg("无效id");
            return result;
        }
        TenantCash bean = dataDao.findById(request.getId());
        if (bean == null) {
            result.setCode(502);
            result.setMsg("无效id");
            return result;
        }
        handleData(request, bean);
        result = new TenantCashResponseConvert().conver(bean);
        return result;
    }

    private void handleData(TenantCashDataRequest request, TenantCash bean) {
       TenantBeanUtils.copyProperties(request,bean);
           if(request.getCreator()!=null){
              bean.setCreator(creatorDao.findById(request.getCreator()));
           }
           if(request.getCashConfig()!=null){
              bean.setCashConfig(cashConfigDao.findById(request.getCashConfig()));
           }

    }

    @Override
    public TenantCashResponse delete(TenantCashDataRequest request) {
        TenantCashResponse result = new TenantCashResponse();
        if (request.getId() == null) {
            result.setCode(501);
            result.setMsg("无效id");
            return result;
        }
        dataDao.deleteById(request.getTenant(),request.getId());
        return result;
    }

    @Override
    public TenantCashResponse view(TenantCashDataRequest request) {
        TenantCashResponse result=new TenantCashResponse();
        TenantCash bean = dataDao.findById(request.getTenant(), request.getId());
        if (bean==null){
            result.setCode(1000);
            result.setMsg("无效id");
            return result;
        }
        result=new TenantCashResponseConvert().conver(bean);
        return result;
    }
    @Override
    public TenantCashList list(TenantCashSearchRequest request) {
        TenantCashList result = new TenantCashList();

        List<Filter> filters = new ArrayList<>();
        filters.add(Filter.eq("tenant.id", request.getTenant()));
        filters.addAll(FilterUtils.getFilters(request));
        List<Order> orders = new ArrayList<>();
        if ("asc".equals(request.getSortMethod())){
           orders.add(Order.asc(""+request.getSortField()));
        }
        else if ("desc".equals(request.getSortMethod())){
           orders.add(Order.desc(""+request.getSortField()));
        }else{
           orders.add(Order.desc("id"));
        }
        List<TenantCash> organizations = dataDao.list(0, request.getSize(), filters, orders);

        TenantCashSimpleConvert convert=new TenantCashSimpleConvert();
        ConverResourceUtils.converList(result, organizations,convert);
        return result;
    }

    @Override
    public TenantCashPage search(TenantCashSearchRequest request) {
        TenantCashPage result=new TenantCashPage();
        Pageable pageable = new PageableConver().conver(request);
        pageable.getFilters().addAll(FilterUtils.getFilters(request));
        pageable.getFilters().add(Filter.eq("tenant.id", request.getTenant()));
        if ("asc".equals(request.getSortMethod())){
            pageable.getOrders().add(Order.asc(""+request.getSortField()));
        }
        else if ("desc".equals(request.getSortMethod())){
            pageable.getOrders().add(Order.desc(""+request.getSortField()));
        }else{
            pageable.getOrders().add(Order.desc("id"));
        }
        Page<TenantCash> page=dataDao.page(pageable);

        TenantCashSimpleConvert convert=new TenantCashSimpleConvert();
        ConverResourceUtils.converPage(result,page,convert);
        return result;
    }
}
